/*
 * Formatter class
 *
 * Copyright 2009, Gerben van Veenendaal (http://www.gerbenvv.nl)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * See the GNU General Public License in the COPYING file at the
 * root directory of this project for more details.
 */

#ifndef _FORMATTER_H
#define _FORMATTER_H

#include "common.h"
#include "node.h"
#include "exception.h"

namespace PhpTidyLib{

/* state enumeration */
enum EState {
	S_NONE,
	S_CONTROL_STRUCTURE,
	S_ELSE,
	S_CURLY_BRACKETS,
	S_BRACKETS
};

/* assignment structure */
struct SAssignment {
	CNode *var;
	CNode *semicolon;
	uint   length;
};

class PhpFormatter
{
public:
	PhpFormatter(void);
	~PhpFormatter(void);

	void Init(void);
	void Run(string &strOut);

	void   Write(CNode *);
	string GetIndent(int = 0, bool = false);

	void   AddAssignment(CNode *, CNode *semicolon);
	void   FormatAssignments(void);

	void   HandleSemicolon(CNode *);

	void   FormatOperator(CNode *, CNode *, CNode *, bool);
	void   FormatOpenCurlyBracket(CNode **, bool = false);
	void   FormatCloseCurlyBracket(CNode *);
	void   FormatLongComment(CNode *);

	CNode *MoveShortComment(CNode *);
	void   AddStructureComment(CNode *, CNode *);

	//FILE *file;
	uint indent;

	stack<SAssignment> assignments;
	uint maxvarlength;

	//vector<EState> states;
	stack<EState> states;

	CNode *first_node;
	CNode *last_node;
};

/* writes node to file */
inline void PhpFormatter::Write(CNode *node)
{
	node = node;
	//uint length = node->token.length();
	//if (fwrite(node->token.c_str(), length, 1, file) != 1) {
	//	throw new CException(E_INTERNAL, "Couldn\'t write output file!");
	//}
	//cout << "Written: " << length << " bytes.\n";
}

/* handles fake semicolons */
inline void PhpFormatter::HandleSemicolon(CNode *node)
{
	node = node;
	/* check if it is a close tag */
	if (node->token[0] != ';') {
		node->token = ";\n" + node->token; //NOTE: changing!
	}
}

/* formats operators */
inline void PhpFormatter::FormatOperator(CNode *first, CNode *second, CNode *third, bool surround)
{
	/* surround operator with spaces */
	if (surround)
		second->Surround(' ');

	/* join them in first */
	//first->Append(second);
	first->Append(third);
}
}
#endif
